package pers.xiaojun.boot.module.infra.service.config;

;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Sets;
import org.springframework.stereotype.Service;
import pers.xiaojun.boot.common.exception.BusinessException;
import pers.xiaojun.boot.common.util.CollectionUtils;
import pers.xiaojun.boot.module.infra.controller.config.vo.ConfigQueryReqVO;
import pers.xiaojun.boot.module.infra.controller.config.vo.ConfigSaveReqVO;
import pers.xiaojun.boot.module.infra.dao.entity.ConfigDO;
import pers.xiaojun.boot.module.infra.dao.mapper.ConfigMapper;
import pers.xiaojun.boot.module.infra.enums.ConfigTypeEnum;
import pers.xiaojun.boot.mybatis.core.convert.PageConvert;
import pers.xiaojun.boot.mybatis.core.query.LambdaQueryWrapperX;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import static pers.xiaojun.boot.module.infra.constants.BusinessCodeConstants.*;

/**
 * 参数配置服务实现类
 *
 * @author xiaojun
 * @since 2025-11-09
 */
@Service
public class ConfigServiceImpl extends ServiceImpl<ConfigMapper, ConfigDO> implements ConfigService {


    @Override
    public ConfigDO saveConfig(ConfigSaveReqVO saveVO) {
        validateConfigBasicInfo(null, saveVO.getConfigKey());

        ConfigDO config = BeanUtil.toBean(saveVO, ConfigDO.class);
        config.setType(ConfigTypeEnum.CUSTOM.getType());
        this.baseMapper.insert(config);

        return config;
    }

    @Override
    public ConfigDO updateConfig(ConfigSaveReqVO updateVO) {
        validateConfigExists(updateVO.getId());
        validateConfigBasicInfo(updateVO.getId(), updateVO.getConfigKey());

        ConfigDO config = BeanUtil.toBean(updateVO, ConfigDO.class);
        this.baseMapper.updateById(config);

        return config;
    }

    @Override
    public void removeConfigById(Long configId) {
        ConfigDO config = validateConfigExists(configId);
        if (ConfigTypeEnum.isSystemType(config.getType())) {
            throw new BusinessException(CONFIG_SYSTEM_CANNOT_DELETE);
        }

        this.baseMapper.deleteById(configId);
    }

    @Override
    public void removeConfigByIds(List<Long> configIds) {
        List<ConfigDO> configs = this.baseMapper.selectByIds(configIds);

        // 判断是否有内置参数，记录并抛出错误
        HashSet<String> configKeys = new HashSet<>();
        configs.forEach(config -> {
            if (ConfigTypeEnum.isSystemType(config.getType())) {
                configKeys.add(config.getConfigKey());
            }
        });
        if (CollUtil.isNotEmpty(configKeys)) {
            throw new BusinessException(
                    CONFIG_SYSTEM_CANNOT_DELETE.getCode(),
                    StrUtil.format("参数Key {} 为内置参数，无法删除", configKeys)
            );
        }
        // 判断参数是否都存在
        if (configs.size() != configIds.size()) {
            Set<Long> notFindIds = Sets.difference(
                    new HashSet<>(configIds),
                    CollectionUtils.convertSet(configs, ConfigDO::getId)
            );
            throw new BusinessException(CONFIG_NOT_EXISTS.getCode(), StrUtil.format("参数id {} 不存在", notFindIds));
        }

        this.baseMapper.deleteByIds(configIds);
    }

    @Override
    public ConfigDO getConfigById(Long configId) {
        return validateConfigExists(configId);
    }

    @Override
    public ConfigDO getConfigByKey(String configKey) {
        return this.baseMapper.selectByKey(configKey);
    }

    @Override
    public Page<ConfigDO> listConfigsPage(ConfigQueryReqVO queryVO) {
        return this.baseMapper.selectPage(PageConvert.INSTANCE.toPage(queryVO), new LambdaQueryWrapperX<ConfigDO>()
                .likeIfPresent(ConfigDO::getName, queryVO.getName())
                .likeIfPresent(ConfigDO::getConfigKey, queryVO.getConfigKey())
                .eqIfPresent(ConfigDO::getType, queryVO.getType())
                .betweenIfPresent(ConfigDO::getCreateTime, queryVO.getCreateTime())
        );
    }

    /**
     * 校验参数是否存在
     *
     * @param configId 参数Id
     * @return 参数
     */
    private ConfigDO validateConfigExists(Long configId) {
        if (configId == null) {
            return null;
        }
        ConfigDO config = this.baseMapper.selectById(configId);
        if (config == null) {
            throw new BusinessException(CONFIG_NOT_EXISTS);
        }
        return config;
    }

    /**
     * 校验参数基本信息
     *
     * @param configId  参数Id
     * @param configKey 参数键
     */
    private void validateConfigBasicInfo(Long configId, String configKey) {
        if (configKey == null) {
            return;
        }
        ConfigDO config = this.baseMapper.selectByKey(configKey);
        if (config != null && !config.getId().equals(configId)) {
            throw new BusinessException(CONFIG_KEY_EXISTS);
        }
    }

}
